package messages;

import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;

import javax.swing.JOptionPane;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import security.crypto.AssimEncryption;
import utils.Base64Processing;
import utils.XmlSerializationUtils;
import connection.CitizenCardInterface;
import connection.exception.CardErrorException;

public class CcPKExchangeMessage implements Convertible {
	
	private static final long serialVersionUID = 1L;

	private String _userId;
	
	private String _publicKey;
	
	private String _timestamp;
	
	private String _publicKeyAuth;
	
	private final long _maxThresholdMilis = 600000;
	
	public CcPKExchangeMessage(){}
	
	public CcPKExchangeMessage(String userId, PublicKey publicKey){
		_userId = userId;
		_publicKey = Base64Processing.encodeData(publicKey.getEncoded());
		_timestamp = (new Long(System.currentTimeMillis())).toString();
				
		try {
			_publicKeyAuth = Base64Processing.encodeData(CitizenCardInterface.SignData(_publicKey+" "+_timestamp));
		} catch (CardErrorException e) {
			JOptionPane.showMessageDialog(null, "O cart�o n�o est� conectado no leitor");
		}
	}
	
	public String getUserId() {
		return _userId;
	}
	
	public PublicKey getPublicKey(Certificate certificate) {
		boolean clientAuth = AssimEncryption.verifyCcSignature(_publicKey+" "+_timestamp, _publicKeyAuth, certificate);
		
		long remoteTS = Long.parseLong(_timestamp);
		long thresholdTS = System.currentTimeMillis()-_maxThresholdMilis;
		
		if(remoteTS < thresholdTS)
			return null;		
		
		if(clientAuth){			
			try {
				byte[] publicKeyEncoded = Base64Processing.decodeData(_publicKey);
				
				X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKeyEncoded);
				KeyFactory keyFactory = KeyFactory.getInstance("RSA");
				
				return keyFactory.generatePublic(pubKeySpec);
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			} catch (InvalidKeySpecException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public Element convertToCanonic(Document doc) {
		Element el = doc.createElement("CcPKExchangeMessage");

		if (_userId != null) {
			Element childEl = doc.createElement("UserId");
			childEl.setTextContent(_userId);
			el.appendChild(childEl);
		}
		
		if (_publicKey != null) {
			Element childEl = doc.createElement("PublicKey");
			childEl.setTextContent(_publicKey);
			el.appendChild(childEl);
		}
		
		if (_timestamp != null) {
			Element childEl = doc.createElement("Timestamp");
			childEl.setTextContent(_timestamp);
			el.appendChild(childEl);
		}
		
		if (_publicKeyAuth != null) {
			Element childEl = doc.createElement("PublicKeyAuthenticator");
			childEl.setTextContent(_publicKeyAuth);
			el.appendChild(childEl);
		}
		
		return el;
	}

	public Object convertFromCanonic(Element el) {
		this._userId = XmlSerializationUtils.getTextValue(el, "UserId");
		this._publicKey = XmlSerializationUtils.getTextValue(el, "PublicKey");
		this._timestamp = XmlSerializationUtils.getTextValue(el, "Timestamp");
		this._publicKeyAuth = XmlSerializationUtils.getTextValue(el, "PublicKeyAuthenticator");
		return this;
	}
}
